package org.rcgwt.client.ui.validator.impl;

import java.util.Map;

import org.rcgwt.client.ui.validator.IChecker;
import org.rcgwt.client.ui.validator.IClientValidatorContext;
import org.rcgwt.client.ui.validator.messages.Severity;
import org.rcgwt.client.util.Pattern;
import org.rcgwt.client.util.PatternBuilder;

/**
 * A date checker with parameters, thats checks the date structure by format, or
 * separator-signs...
 * 
 * @author Elian ORIOU
 * 
 */

public class DateChecker implements IChecker {

	// The digits separator
	private static String sepSign = "/";
	// The date format (us|eu)
	private static String format = "eu";
	// Patterns
	private Pattern US_DATE_PATTERN;

	private Pattern EU_DATE_PATTERN;

	private Map<String, String> parameters;

	public DateChecker(Map<String, String> p) {
		parameters = p;

		US_DATE_PATTERN = Pattern.compile("^[01][0-9][" + sepSign
				+ "]?[0123][0-9][" + sepSign + "]?[0-9]{2,4}$");

		EU_DATE_PATTERN = Pattern.compile("^[0123][0-9][" + sepSign
				+ "]?[01][0-9][" + sepSign + "]?[0-9]{2,4}$");

		/* Gathering parameters (separator sign & format) */
		if (parameters.containsKey("date.sepSign")) {
			sepSign = parameters.get("date.sepSign");

			US_DATE_PATTERN = Pattern.compile(PatternBuilder.encode(
					"^[01][0-9][%%1]?[0123][0-9][%%2]?[0-9]{2,4}$", sepSign,
					sepSign));
			EU_DATE_PATTERN = Pattern.compile(PatternBuilder.encode(
					"^[0123][0-9][%%1]?[01][0-9][%%2]?[0-9]{2,4}$", sepSign,
					sepSign));
		}
		if (parameters.containsKey("date.format")) {
			format = parameters.get("date.format");
		}
	}

	@Override
	public boolean check(IClientValidatorContext context, String s) {

		/* Analyzing the date structure */
		if ((format.equals("us") && US_DATE_PATTERN.matches(s))
				|| (format.equals("eu") && EU_DATE_PATTERN.matches(s))) {
			/* The date year */
			int year = Integer.parseInt(s.substring(6));
			/* If both parameters "begin" & "end" are specified */
			if (parameters != null && parameters.containsKey("date.begin")
					&& parameters.containsKey("date.end")) {
				int beginDate = Integer.parseInt(parameters.get("date.begin"));
				int endDate = Integer.parseInt(parameters.get("date.end"));

				/* If the date is between "beginDate" & "endDate" */
				if (year >= beginDate && year <= endDate)
					return true;
				else {
					context.addMessage(context.getMessagesProvider()
							.BetweenDateErrorShort(beginDate, endDate), context
							.getMessagesProvider().BetweenDateError(beginDate,
									endDate), Severity.WARN);
					return false;
				}
			}
			/* If parameter "begin" is specified (only) */
			if (parameters != null && parameters.containsKey("date.begin")) {
				int beginDate = Integer.parseInt(parameters.get("date.begin"));

				if (year >= beginDate)
					return true;
				else {
					context.addMessage(context.getMessagesProvider()
							.AfterYearErrorShort(beginDate), context
							.getMessagesProvider().AfterYearError(beginDate),
							Severity.WARN);
					return false;
				}
			}
			/* If parameter "end" is specified (only) */
			else if (parameters != null && parameters.containsKey("date.end")) {
				int endDate = Integer.parseInt(parameters.get("date.end"));

				if (year <= endDate)
					return true;
				else {
					context.addMessage(context.getMessagesProvider()
							.AfterYearErrorShort(endDate), context
							.getMessagesProvider().AfterYearError(endDate),
							Severity.WARN);
					return false;
				}
			}
			return true;
		}
		context.addMessage(context.getMessagesProvider().StructureErrorShort(),
				context.getMessagesProvider().StructureError(), Severity.ERROR);
		return false;
	}
}
